package org.jypj.dev.util;

import com.swetake.util.Qrcode;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class TwoDimensionCode {

    public static final int QR_CODE_SIZE = 2;

    /**
     * logo的边长
     */
    public static final int LOGO_WIDTH = 40;

    /**
     * 文字显示使用的高度
     */
    public static final int TEXT_SHOW_HEIGHT = 30;

    /**
     * @param content     二维码存储内容
     * @param imgPath     图片生成的路径
     * @param imgType     生成的图片类型
     * @param logoPath    要添加的logo的路径 http://xxxxx
     * @param showContent 要在二维码上显示的文本
     */
    public void encoderQRCode(String content, String showContent, String logoPath, String imgPath, String imgType) {
        try {
            BufferedImage bufImg = this.qRCodeCommon(content);
            if (StringUtil.isNotEmpty(logoPath)) {
                bufImg = insertLogo(bufImg, logoPath);
            }
            if (StringUtil.isNotEmpty(showContent)) {
                bufImg = insertText(bufImg, showContent);
            }
            File imgFile = new File(imgPath);
            // 生成二维码QRCode图片  
            ImageIO.write(bufImg, imgType, imgFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成二维码(QRCode)图片的公共方法
     *
     * @param content 存储内容
     * @return
     */
    private BufferedImage qRCodeCommon(String content) {
        BufferedImage bufImg = null;
        try {
            Qrcode qrcodeHandler = new Qrcode();
            // 设置二维码排错率，可选L(7%)、M(15%)、Q(25%)、H(30%)，排错率越高可存储的信息越少，但对二维码清晰度的要求越小  
            qrcodeHandler.setQrcodeErrorCorrect('H');
            qrcodeHandler.setQrcodeEncodeMode('B');
            // 设置设置二维码尺寸，取值范围1-40，值越大尺寸越大，可存储的信息越大  1点为13字符
            qrcodeHandler.setQrcodeVersion(QR_CODE_SIZE);
            // 获得内容的字节数组，设置编码格式  
            byte[] contentBytes = content.getBytes("utf-8");
            // 图片尺寸  
            int imgSize = 240 + 12 * (QR_CODE_SIZE - 1);
            bufImg = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB);
            Graphics2D gs = bufImg.createGraphics();
            // 设置背景颜色  
            gs.setBackground(Color.WHITE);
            gs.clearRect(0, 0, imgSize, imgSize);
            // 设定图像颜色> BLACK
            gs.setColor(Color.BLACK);
            // 设置偏移量，不设置可能导致解析出错
            int pixoff = 3;
            // 输出内容> 二维码  
            if (contentBytes.length > 0 && contentBytes.length < 800) {
                boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);
                for (int i = 0; i < codeOut.length; i++) {
                    for (int j = 0; j < codeOut.length; j++) {
                        if (codeOut[j][i]) {
                            gs.fillRect(j * 10 + pixoff, i * 10 + pixoff, 10, 10);
                        }
                    }
                }
            } else {
                throw new Exception("QRCode content bytes length = " + contentBytes.length + " not in [0, 800].");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufImg;
    }

    /**
     * 插入文字
     *
     * @param bufImage
     * @param showContent
     * @return
     */
    public BufferedImage insertText(BufferedImage bufImage, String showContent) {
        int width = bufImage.getWidth();
        int height = bufImage.getHeight();
        BufferedImage outImage = new BufferedImage(width, height + TEXT_SHOW_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
        //设置字体
        Graphics2D gs = outImage.createGraphics();
        gs.setColor(Color.WHITE);
        gs.drawImage(bufImage, 0, 0, bufImage.getWidth(), bufImage.getHeight(), null);

        gs.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 26);
        FontMetrics metrics = gs.getFontMetrics(font);
        String s = half2Full(showContent);//将半角英文转为全角
        int strLen = metrics.stringWidth(s); //得到文本的长度
        gs.setFont(font); //设置字体
        int startY = height + 22;//设置绘画文字的起始Y坐标
        if (strLen > width) {//如果文本过长需要换行显示
            String s1 = s.substring(0, 9);
            int s1Len = metrics.stringWidth(s1);
            int startX = (width - s1Len) / 2;
            String s2 = s.substring(9);
            gs.drawString(s1, startX, startY);//画字符串
            gs.dispose();
            outImage.flush();
            outImage = insertText(outImage, s2);//递归实现
        } else {
            int s1Len = metrics.stringWidth(s);
            int startX = (width - s1Len) / 2;
            gs.drawString(s, startX, startY);//画字符串
            gs.dispose();
            outImage.flush();
        }
        return outImage;
    }

    /**
     * 插入logo
     *
     * @param bufImage
     * @param logoPath
     * @return
     */
    public BufferedImage insertLogo(BufferedImage bufImage, String logoPath) {
        // 创建url;
        try {
            URL url = new URL(logoPath);
            // 创建url连接;
            HttpURLConnection urlconn = (HttpURLConnection) url.openConnection();
            // 链接远程服务器;
            urlconn.connect();
            //根据路径得到输出流
            InputStream inputStream = urlconn.getInputStream();

            Image src = ImageIO.read(inputStream);

            int width = src.getWidth(null);
            int height = src.getHeight(null);
            //压缩LOGO
            if (width > LOGO_WIDTH) {
                width = LOGO_WIDTH;
            }
            if (height > LOGO_WIDTH) {
                height = LOGO_WIDTH;
            }
            Image image = src.getScaledInstance(width, height,
                    Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            src = image;
            // 插入LOGO
            Graphics2D graph = bufImage.createGraphics();
            int bufWidth = bufImage.getWidth();
            int x = (bufWidth - width) / 2;
            int y = (bufWidth - height) / 2;
            graph.drawImage(src, x, y, width, height, null);
            Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
            graph.setStroke(new BasicStroke(3f));
            graph.draw(shape);
            graph.dispose();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bufImage;
    }

    /**
     * 将文字半角转为全角
     *
     * @param value
     * @return
     */
    public String half2Full(String value) {
        char[] cha = value.toCharArray();
        for (int i = 0; i < cha.length; i++) {
            if (cha[i] == 32) {
                cha[i] = (char) 12288;
            } else if (cha[i] < 127) {
                cha[i] = (char) (cha[i] + 65248);
            }
        }
        return new String(cha);
    }

    public static void main(String[] args) {
        String imgPath = "E:/ewm/test.png";
        String encoderContent = "20170320175412";
        String logoPath = "http://localhost/upload/thingLogo/yc1.png";
        TwoDimensionCode handler = new TwoDimensionCode();
        handler.encoderQRCode(encoderContent, "中文测试中文测试试中文测试中阿萨德asfqweqweawqsdaqwe文测试试文测试试文测试试文测试试文测试试", logoPath, imgPath, "png");

        System.out.println("========encoder success");
    }
}  